<?

include_once('lib/database.php');

class AGModel
{
  var $modelName;
  var $assocTableName;
  
  function AGModel($modelName)
  {
    $this->modelName = $modelName;
  }
  
  function bindTable($tableName)
  {
    $assocTableName = $tableName;
  }
  
}

class AGDatasetModel extends AGModel
{
  var $data, $table;
  
  function __construct($modelName) 
  {
    parent::__construct($modelName);
  }
  
  function Save($dataset = null)
  {
    if ($dataset == null)
      $dataset = $this->ds;
    if (isset($this->table))
      return(DB_UpdateDataset($this->table, $dataset));
    else
      logError('AGDatasetModel['.$this->modelName.'].Save() error: no tablename given');
  }

  function Load($id)
  {
    if (isset($this->table))
    {
      $this->ds = DB_GetDataset($this->table, $id);
      return($this->ds);
    }
    else
      logError('AGDatasetModel['.$this->modelName.'].Load() error: no tablename given');
  }

  function Delete($id)
  {
    if (isset($this->table))
      DB_RemoveDataset($this->table, $id);
    else
      logError('AGDatasetModel['.$this->modelName.'].Delete() error: no tablename given');
  }
  
  function getList($filter = array(), $options = array())
  {
    if (isset($this->table))
      return(DB_ListItems($this->table, $filter, $options));  
    else
      logError('AGDatasetModel['.$this->modelName.'].Delete() error: no tablename given');
  }

}


class AGUserModel extends AGModel
{
  var $data;
  
  function __construct($modelName) 
  {
    global $config;
    parent::__construct($modelName);
    include_once('lib/database.php');
    $this->table = 'users';
    $this->usernameField = 'username';
    $this->passwordField = 'password';
    $this->rolesField = 'roles';
    $this->emailField = 'email';
    $this->sessionVar = $config['session.useridfield']; 
    $this->loginOnSignup = false;
    $this->enableSignup = true;
    $this->randomPasswordLength = 6;
    $this->signUpTemplate = 'lib/templates/email-user-signup.php';
    $this->enableAccountMenu = true;
    $this->controllerName = $this->modelName;
  }
  
  function loadIdentity($idKey = null)
  {
    if (!isset($this->data))
    {
      $this->bindTable($this->table);
      if (!isset($idKey)) $idKey = $this->getId();
      $this->data = DB_GetDataset($this->table, $idKey);  
    }
  }
  
  function Load()
  {
    $this->loadIdentity($this->getId());
  }
  
  function GetId()
  {
    return($_SESSION[$this->sessionVar]);
  }
  
  function Logout()
  {
    unset($_SESSION[$this->sessionVar]);
    $this->data = array();
  }
  
  function matchPassword($input, &$dataset)
  {
    return($dataset[$this->passwordField] == md5($input));
  }
  
  function randomPassword()
  {
    return(substr(md5(time()), 0, $this->randomPasswordLength));
  }
  
  function GetRoles()
  {
    $this->loadIdentity();
    $roles = explode($this->data[$this->rolesField]);
    if (!is_array($roles)) $roles = array();
    return($roles);
  }
  
  function SetRoles($rolesArray)
  {
    $this->loadIdentity();
    $this->data[$this->rolesField] = implode(',', $rolesArray);
    DB_UpdateDataset($this->table, $this->data);
  }
  
  function encodePassword($pwd)
  {
    return(md5($pwd));
  }
  
  function loginForm($formtemplate = 'lib/agusermodel.loginform.php')
  {
    include($formtemplate);
  }
  
  function Login($email, $passwordmatch)
  {
    $keys = DB_GetKeys($this->table);
    $this->userkeyField = $keys[0];
    $pds = DB_GetDataset($this->table, $email, $this->usernameField);
    if (sizeof($pds)==0 OR !$this->matchPassword($passwordmatch, $pds))
      return(false);
    $this->data = $pds;
    $_SESSION[$this->sessionVar] = $pds[$this->userkeyField];
    return(true);
  }
  
  function Signup($usr)
  {
    $result = '';
    
    if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", 
              $usr[$this->emailField])) return('Please enter a valid email address.');
    
    $pds = DB_GetDataset($this->table, $usr[$this->emailField], $this->emailField);
    if (sizeof($pds)>0) return('This email address is already registered.');
    
    $password = $this->randomPassword();
    $usr[$this->passwordField] = $this->encodePassword($password);
    $usr[$this->usernameField] = $usr[$this->emailField];
    
    $usr[$this->userkeyField] = DB_UpdateDataset($this->table, $usr);
    
    if ($usr[$this->userkeyField] > 0)
    {
      $params = $usr;
      $params['password'] = $password;
      send_mail($this->emailField, $this->signUpTemplate, $params);
      
      $this->data = $usr;
      
      if ($this->loginOnSignup)
      {
        $_SESSION[$this->sessionVar] = $usr[$this->userkeyField];
        $this->createMenu();
      }
    }
    else
    {
      $result = 'database error, please check the field names';
    }
    return($result);
  }
  
  function check_role($singleRole, &$userRoles)
  {
    $result = true;
    $negate = false;
    
    if (substr($singleRole, 0, 1) == '+') 
    {
      $singleRole = substr($singleRole, 1);
    }
    else if (substr($singleRole, 0, 1) == '-')
    { 
      $negate = true;
      $singleRole = substr($singleRole, 1);
    }
    
    $key = array_search($singleRole, $userRoles);
    if ($key === false) $result = false;
    if ($negate) $result = !$result;
    
    return($result);
  }
  
  function has_role($roleStr)
  {
    $userRoles = $this->getRoles();
    $roles = explode(' or ', strtolower($roleStr));
    $meetsOneOrMore = false;
    
    foreach ($roles as $requirementStr)
    {
      $meetsRequirements = true;
      foreach(explode(',', $requirementStr) as $reqRole)
        if (!$this->check_role(trim($reqRole), $userRoles)) $meetsRequirements = false;
      if ($meetsRequirements) $meetsOneOrMore = true;
    }
    
    return($meetsOneOrMore);
  }
  
  function require_role($roleStr, $msg = 'insufficient rights!')
  {
    if (!$this->has_role($roleStr))
      die($msg);
  }

  function createMenu()
  {
    global $config;
    $config['accountmenu'] = array();
    if (isset($_SESSION[$this->sessionVar]))
    {
      $config['accountmenu']['logout'] = 
        array('url' => actionUrl('logout', $this->controllerName), 'caption' => 'Logout');
      if ($this->enableAccountMenu)
        $config['accountmenu']['account'] = 
        array('url' => actionUrl('index', $this->controllerName), 'caption' => 'My Account');
    }
    else
    {
      $config['accountmenu']['login'] = 
      array('url' => actionUrl('login', $this->controllerName), 'caption' => 'Login');
      if ($this->enableSignup)
        $config['accountmenu']['signup'] = 
        array('url' => actionUrl('signup', $this->controllerName), 'caption' => 'Sign up');
    }
  }
  
}


?>
